"""
处理篡改监测套餐
1、给付费套餐默认加上篡改监测, 支持web漏洞监测的套餐都默认支持篡改监测
2、给付费用户开通篡改监测
"""
import arrow
from app.db.models.balances import Balances
from app.db.models.packages import Packages
from app.db.models.charges import Charges
from app.db.models.meta_limit import TypeFreq
from app.libs.enums import TaskType


def get_pkg_ids():
    """
    scanv_usability_senior: ScanV_可用性_高级版,
    scanv_usability_enterprise: ScanV_可用性_企业版
    scanv_free: 免费版
    """
    no_pkg_key = [
        "scanv_usability_senior",
        "scanv_usability_enterprise",
        "scanv_free",
    ]
    pkg_ids = Packages.objects.filter(key__nin=no_pkg_key, feature__vulTask=True).distinct("id")
    return pkg_ids


def get_freq_data(total):
    freq = TypeFreq()
    freq.taskType = TaskType.change_check.value
    freq.total = total
    return freq


def update_pkg_data(pkg_ids=None):
    """更新套餐数据，给支持web漏洞监测的套餐增加篡改监测功能"""
    pkg_ids = get_pkg_ids() if not pkg_ids else pkg_ids
    for pkg in Packages.objects.filter(id__in=pkg_ids):
        if not (feature := getattr(pkg, "feature", None)):
            continue
        if not feature.vulTask:
            continue
        pkg.limit.changeCheckMaxFreq = get_freq_data(86400000)
        pkg.limit.changeCheckMaxDepth = get_freq_data(10)
        pkg.limit.changeCheckMaxPage = get_freq_data(1000)
        pkg.limit.changeCheckMaxBaseChange = get_freq_data(5)
        pkg.limit.changeCheckMaxKeyword = get_freq_data(100)
        pkg.limit.changeCheckMaxResource = get_freq_data(100)
        pkg.feature.changeCheckTask = True
        pkg.save()
        print(f"更新套餐: {pkg.id}, {pkg.name}, {pkg.key}")


def get_charge_data(pack, balance, func_type, pack_item):
    now_datetime = arrow.utcnow().datetime
    _charge_item = {
        'createTime': now_datetime,
        'updateTime': now_datetime,
        'packId': pack.id,
        'taskType': pack_item.taskType,
        'limitType': pack_item.limitType,
        'total': pack_item.total,
        'expireTime': balance.planExpireTime,
        'uid': balance.uid,
        'number': 1,
        'funcType': func_type,
        'chargeType': pack.chargeType
    }
    return _charge_item


def update_user_data(user_ids=None, pkg_ids=None):

    query = {}
    all_pkg_ids = get_pkg_ids()
    if user_ids:
        query.update({"uid__in": user_ids})
    if pkg_ids:
        query.update({"planId__in": pkg_ids})
    if not query:
        query.update({"planId__in": all_pkg_ids})
    pkg_map = {p.id: p for p in Packages.objects.filter(id__in=all_pkg_ids)}
    for balance in Balances.objects.filter(**query):
        pkg = pkg_map.get(balance.planId)
        if (not pkg) or (not pkg.feature.changeCheckTask):
            print(f"{balance.id} {balance.uid}, skip, {balance.planId} 该套餐不支持开通")
            continue
        if not balance.planExpireTime:
            print(f"{balance.id} {balance.uid}, skip, 非正常用户，没有过期时间")
            continue
        if arrow.get(balance.planExpireTime).datetime < arrow.utcnow().datetime:
            print(f"{balance.id} {balance.uid}, skip, 套餐已经过期")
            continue
        if balance.feature.changeCheckTask or Charges.objects.filter(
                taskType=TaskType.change_check.value, uid=balance.uid):
            print(f"{balance.id} {balance.uid}, skip, 已经开通过，不再进行脚本开通")
            continue

        insert_charges = []
        for func_type in ["changeCheckMaxFreq", "changeCheckMaxDepth", "changeCheckMaxPage",
                          "changeCheckMaxBaseChange", "changeCheckMaxKeyword", "changeCheckMaxResource"]:
            pack_item = getattr(pkg.limit, func_type)
            setattr(balance.balance, func_type, pack_item)
            charge_data = get_charge_data(pkg, balance, func_type, pack_item)
            insert_charges.append(Charges().from_dict(charge_data))
        balance.feature.changeCheckTask = True
        balance.save()
        # 添加开通记录
        if insert_charges:
            Charges.objects.insert(insert_charges)
